﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace VOL.Core.Utilities
{
    /// <summary>
    /// 防止重复调用的API工具类
    /// </summary>
    public class PreventAPI
    {
        private static readonly Lazy<PreventAPI> _instance = new Lazy<PreventAPI>(() => new PreventAPI());
        private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphores = new ConcurrentDictionary<string, SemaphoreSlim>();
        private readonly ConcurrentDictionary<string, DateTime> _lastCallTimes = new ConcurrentDictionary<string, DateTime>();
        private readonly ConcurrentDictionary<string, CancellationTokenSource> _debounceTimers = new ConcurrentDictionary<string, CancellationTokenSource>();

        /// <summary>
        /// 单例实例
        /// </summary>
        public static PreventAPI Instance => _instance.Value;

        private PreventAPI() { }

        /// <summary>
        /// 防抖函数
        /// </summary>
        /// <param name="key">唯一标识</param>
        /// <param name="callback">回调函数</param>
        /// <param name="delay">延迟时间（毫秒）</param>
        public void Debounce(string key, Action callback, int delay = 300)
        {
            if (_debounceTimers.TryGetValue(key, out var cts))
            {
                cts.Cancel();
            }

            cts = new CancellationTokenSource();
            _debounceTimers[key] = cts;

            Task.Delay(delay, cts.Token)
                .ContinueWith(t =>
                {
                    if (!t.IsCanceled)
                    {
                        callback();
                        _debounceTimers.TryRemove(key, out _);
                    }
                });
        }

        /// <summary>
        /// 异步防抖函数
        /// </summary>
        public async Task DebounceAsync(string key, Func<Task> callback, int delay = 300)
        {
            if (_debounceTimers.TryGetValue(key, out var cts))
            {
                cts.Cancel();
            }

            cts = new CancellationTokenSource();
            _debounceTimers[key] = cts;

            try
            {
                await Task.Delay(delay, cts.Token);
                await callback();
            }
            catch (OperationCanceledException)
            {
                // 忽略取消操作
            }
            finally
            {
                _debounceTimers.TryRemove(key, out _);
            }
        }

        /// <summary>
        /// 节流函数
        /// </summary>
        public void Throttle(string key, Action callback, int limit = 300)
        {
            if (_lastCallTimes.TryGetValue(key, out var lastCallTime))
            {
                var timeSinceLastCall = (DateTime.Now - lastCallTime).TotalMilliseconds;
                if (timeSinceLastCall < limit)
                {
                    return;
                }
            }

            callback();
            _lastCallTimes.AddOrUpdate(key, DateTime.Now, (_, __) => DateTime.Now);
        }

        /// <summary>
        /// 异步节流函数
        /// </summary>
        public async Task ThrottleAsync(string key, Func<Task> callback, int limit = 300)
        {
            if (_lastCallTimes.TryGetValue(key, out var lastCallTime))
            {
                var timeSinceLastCall = (DateTime.Now - lastCallTime).TotalMilliseconds;
                if (timeSinceLastCall < limit)
                {
                    return;
                }
            }

            await callback();
            _lastCallTimes.AddOrUpdate(key, DateTime.Now, (_, __) => DateTime.Now);
        }

        /// <summary>
        /// 防止重复提交
        /// </summary>
        public async Task<T> PreventSubmitAsync<T>(string key, Func<Task<T>> callback, int delay = 1000)
        {
            var semaphore = _semaphores.GetOrAdd(key, _ => new SemaphoreSlim(1, 1));

            try
            {
                if (!await semaphore.WaitAsync(0))
                {
                    throw new InvalidOperationException("请勿重复提交");
                }

                var result = await callback();
                await Task.Delay(delay);
                return result;
            }
            finally
            {
                semaphore.Release();
            }
        }

        /// <summary>
        /// 防止并发访问
        /// </summary>
        public async Task<T> PreventConcurrentAsync<T>(string key, Func<Task<T>> callback)
        {
            var semaphore = _semaphores.GetOrAdd(key, _ => new SemaphoreSlim(1, 1));

            try
            {
                await semaphore.WaitAsync();
                return await callback();
            }
            finally
            {
                semaphore.Release();
            }
        }

        /// <summary>
        /// 清除所有状态
        /// </summary>
        public void Clear()
        {
            foreach (var timer in _debounceTimers.Values)
            {
                timer.Cancel();
            }
            _debounceTimers.Clear();
            _lastCallTimes.Clear();
            _semaphores.Clear();
        }
    }
}
